package TabbedLesson
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	
	import util.Observable;

	public class TabbedLessonModel extends Observable
	{
		private var container_sprite:Sprite;
		private var nativeContainer_object:Object;
		private var stage_lessonContainer:Object;
		private var lessonName_string:String;
		private var lessonPath_string:String;
		private var lessonDiscription_string:String;
		private var lessonEditPass_string:String;
		private var lessonInstructorPass_string:String;
		
		private var windowedLessonView:WindowedLessonView;
		private var tabbedLessonView:TabbedLessonView;
		private var tabbedLessonController:TabbedLessonController;
		private var lessonComponentFactory:LessonComponentFactory;
		
		//--------------------timer related vars---------------------------------------------------------------------//
		private var lessonTimer:Timer;
		private var lessonCurrentTime_int:int;
		private var isLessonTimerRunning_bool:Boolean;
		//------------------------------------------------------------------------------------------------------------//
		
		//---------------------------component mangement related var -------------------------------------------------//
		private var lessonComponentsModel_array:Array = new Array;
		private var lessonComponentsName_array:Array = new Array;
		private var lessonComponentsMinimized_array:Array = new Array;
		
		//-------------------------------------------------------------------------------------------------------------//
		
		//-------------------------------lesson content management vars------------------------------------------------//
		private var lessonChangeInProgress_bool:Boolean;
		private var wasLessonPlayingBeforeChange_bool:Boolean;
		public var lessonEditMode_bool:Boolean;
		//--------------------------------------------------------------------------------------------------------------//
		
		
		public function TabbedLessonModel(lessonInfoObj_object:Object, stage:Object, container:Sprite)
		{
			super();
			this.container_sprite = container;
			this.nativeContainer_object = stage;
			this.lessonName_string = lessonInfoObj_object.lessonName.toString();
			this.lessonPath_string = lessonInfoObj_object.lessonPath.toString();
			this.lessonEditMode_bool=false;
			
			this.tabbedLessonController = new TabbedLessonController(this);
			if(lessonInfoObj_object.openInNewWindow)
			{
				this.windowedLessonView=new WindowedLessonView(this,this.tabbedLessonController,container, this.lessonName_string);
				this.addObserver(this.windowedLessonView);
				this.lessonComponentFactory = new LessonComponentFactory(this,this.windowedLessonView,this.lessonPath_string);
				this.stage_lessonContainer = this.windowedLessonView;
				this.registerWindowedModelToNativeContainer();
			}
			else
			{
				this.tabbedLessonView = new TabbedLessonView(this,this.tabbedLessonController,this.container_sprite, this.lessonName_string);
				this.addObserver(this.tabbedLessonView);
				this.lessonComponentFactory = new LessonComponentFactory(this, this.tabbedLessonView,this.lessonPath_string);
				this.stage_lessonContainer = this.nativeContainer_object;
				this.registerTabbedModelToNativeContainer();
			}
			
			this.initLessonTimerControls();
			this.loadLesson();
			
			this.lessonChangeInProgress_bool=false;
			
			//this.registerModelToNativeContainer();
		}
		
		private function loadLesson():void
		{
			var lessonXml_file:File = new File(this.lessonPath_string+"/"+this.lessonName_string+".xml");
			var urlLoader:URLLoader = new URLLoader;
			var urlRequest:URLRequest = new URLRequest(lessonXml_file.nativePath);
			urlLoader.load(urlRequest);
			urlLoader.addEventListener(Event.COMPLETE, this.lessonXmlLoaded);
		}
		
		private function lessonXmlLoaded(event:Event):void
		{
			var lessonXml_xml:XML = new XML(event.target.data);
			var index:int=0;
			for each (var node:XML in lessonXml_xml.Component)
			{
				this.lessonComponentsName_array.push(node.@name.toString());
				this.lessonComponentsMinimized_array.push(node.@minimized);
			}
			this.lessonDiscription_string = lessonXml_xml.@discription.toString();
			this.lessonEditPass_string = lessonXml_xml.@editPassword.toString();
			this.lessonInstructorPass_string = lessonXml_xml.@instructorPassword.toString();
			
			this.openLesson();
		}
		
		private function openLesson():void
		{
			for each(var compName:String in this.lessonComponentsName_array)
			{
				this.lessonComponentsModel_array.push(this.lessonComponentFactory.makeComponent(compName));
			}
		}
		
		private function saveLesson():void
		{
			this.saveLessonComponents();
			
			var lessonXml_file:File = new File(this.lessonPath_string+"/"+this.lessonName_string+".xml");
			var lessonXml_xml:XML = new XML(<Lesson></Lesson>);
			for(var i:int=0; i<this.lessonComponentsName_array.length; i++)
			{
				var node:XML = new XML(<Component></Component>);
				node.@name = this.lessonComponentsName_array[i];
				node.@minimized = this.lessonComponentsMinimized_array[i];
				lessonXml_xml.appendChild(node);
			}
			
			lessonXml_xml.@name = this.lessonName_string;
			lessonXml_xml.@discription = this.lessonDiscription_string;
			lessonXml_xml.@editPassword = this.lessonEditPass_string;
			lessonXml_xml.@instructorPassword = this.lessonInstructorPass_string;
			
			this.writeXmlFile(lessonXml_file, lessonXml_xml);
		}
		
		private function saveLessonComponents():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "saveData";
			this.sendInfoToLessonComponents(infoObj_object);
			trace("TabbedLessonModel-->saveLessonComponents--->saving component data");
		}
		
		private function writeXmlFile(file:File, xml:XML):void
		{
			var fileStream:FileStream = new FileStream;
			fileStream.open(file, FileMode.WRITE);
			fileStream.writeUTFBytes(xml.toXMLString());
			fileStream.close();
			trace(file.nativePath.toString());
		}
		//-------------------------------------------------------------------------------------------------------------------------//
		
		//------------------------------LessonComponent Management Fuctions------------------------------------------------------------//
		private function instantiateComponent(infoObj_object:Object):void
		{
			this.lessonComponentsName_array.push(infoObj_object.name.toString());
			this.lessonComponentsMinimized_array.push(false);
			this.lessonComponentsModel_array.push(this.lessonComponentFactory.makeComponent(infoObj_object.name.toString()));
		}
		
		private function unregisterComponentModel(infoObj_object:Object):void
		{
			//var index:int=0;
			for(var i:int=0; i<this.lessonComponentsName_array.length; i++)
			{
				if(infoObj_object.name.toString()== this.lessonComponentsName_array[i])
				{
					this.lessonComponentsName_array.splice(i,1);
					this.lessonComponentsModel_array.splice(i,1);
					return;
				}
			}
		}
		
		private function lessonChangeInitiated():void
		{
			if(this.lessonChangeInProgress_bool)
			{
				//do nothing
			}
			{
				this.lessonChangeInProgress_bool=true;
				this.wasLessonPlayingBeforeChange_bool = this.isLessonTimerRunning_bool;
				this.pauseLesson();
			}
		}
		
		private function lessonChangeFinished():void
		{
			this.lessonChangeInProgress_bool = false;
			if(this.wasLessonPlayingBeforeChange_bool)
			{
				this.playLesson();
			}
		}
		
		//-----------------------------------------------------------------------------------------------------------------//
		
		
		//----------------------------------------------Tabbed Lesson Controls-----------------------------------------------------------//
		public function tabTimerExists():Boolean
		{
			return true;
		}
		
		private function registerTabbedModelToNativeContainer():void
		{
			var tabbedObj_object:Object=new Object;
			tabbedObj_object.message = "newTabAdded";
			tabbedObj_object.title="SPLINE -----> "+this.lessonName_string;
			tabbedObj_object.model=this;
			this.nativeContainer_object.incomingMessageGateway(tabbedObj_object);
			trace(this.lessonName_string+" tab's model registered");	
		}
		
		public function closeTab():void
		{
			/* this.pauseLessonTimer();
			 var infoObj2_object:Object = new Object;
			infoObj2_object.message = "close";
			this.sendInfoToLessonComponents(infoObj2_object);
			 */
			var infoObj_object:Object = new Object;
			infoObj_object.message = "closeTab";
			this.setChanged();
			this.notifyObservers(infoObj_object);
		}
		//--------------------------------------------------------------------------------------------------------------------------------//
		
		//-----------------------------------------------------------windowed lessson controls--------------------------------------------//
		private function registerWindowedModelToNativeContainer():void
		{
			var windowedObj_object:Object = new Object;
			windowedObj_object.message = "newWindowAdded";
			windowedObj_object.title = this.lessonName_string;
			windowedObj_object.model = this;
			this.nativeContainer_object.incomingMessageGateway(windowedObj_object);
			trace(this.lessonName_string+" windowed model registered");
		}
		
		public function closeWindow():void
		{
			//this.stopLessonTimer();
			/* var infoObj2_object:Object = new Object;			
			infoObj2_object.message = "close";
			this.sendInfoToLessonComponents(infoObj2_object);
		 */
			var infoObj_object:Object = new Object;
			infoObj_object.message = "closeWindow";
			this.setChanged();
			this.notifyObservers(infoObj_object);
		}
		
		private function unregisterModelFromNativeContainer():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "unregisterWindowedModel";
			infoObj_object.title = this.lessonName_string;
			this.nativeContainer_object.incomingMessageGateway(infoObj_object);
			trace("TabbedLessonModel----> "+this.lessonName_string+" model unregistered. ");
		}
		
		//---------------------------------------------------------------------------------------------------------------------------------//
		
		//----------------------------------Timer Control Functions------------------------------------------------------------------------//
		private function initLessonTimerControls():void
		{
			this.lessonTimer = new Timer(1000);
			this.lessonTimer.addEventListener(TimerEvent.TIMER,this.timerEventListener);
			this.isLessonTimerRunning_bool = false;
		}
		
		private function timerEventListener(event:TimerEvent):void
		{
			this.lessonCurrentTime_int++;
			trace("LesonCurrTime : " + this.lessonCurrentTime_int);
			var infoObj_object:Object = new Object;
			infoObj_object.message = "updateCurrentTime";
			infoObj_object.time = this.lessonCurrentTime_int;
			
			this.sendInfoToStage(infoObj_object);
			this.syncComponentsToLessonTime();
		}
		
		private function playLesson():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonPlayed";
			this.playLessonTimer();
			this.sendInfoToStage(infoObj_object);
			this.sendInfoToLessonComponents(infoObj_object);
		}
		
		private function pauseLesson():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonPaused";
			this.pauseLessonTimer();
			this.sendInfoToStage(infoObj_object);
		}
		
		private function lessonPlayedFromStreamingComponents():void
		{
			//this.playLesson();
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonPlayed";
			this.playLessonTimer();
			this.sendInfoToStage(infoObj_object);
			
		}
		
		private function lessonPausedFromStreamingComponents():void
		{
			this.pauseLesson();
		}

		private function lessonStoppedFromStreamingComponents(infoObj_object:Object):void
		{
			this.syncLessonTimeWithComponent(infoObj_object);
			this.pauseLesson();
		}
		
		private function lessonPlayedFromControlPanel():void
		{
			this.playLessonTimer();
			
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonPlayed";
			infoObj_object.time = this.lessonCurrentTime_int;
			
			this.sendInfoToLessonComponents(infoObj_object);
		}
		
		private function lessonPausedFromControlPanel():void
		{
			this.pauseLessonTimer();
			
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonPaused";
			infoObj_object.time = this.lessonCurrentTime_int;
			
			this.sendInfoToLessonComponents(infoObj_object);
		}
		
		private function lessonStoppedFromControlPanel():void
		{
			this.stopLessonTimer();
			var infoObj_object:Object = new Object;
			infoObj_object.message = "lessonStopped";
			infoObj_object.time = this.lessonCurrentTime_int;
			
			this.sendInfoToLessonComponents(infoObj_object);
			
		}
		
		private function playLessonTimer():void
		{
			this.lessonTimer.start();
			this.isLessonTimerRunning_bool=true;
		}
		
		private function pauseLessonTimer():void
		{
			this.lessonTimer.stop();
			this.isLessonTimerRunning_bool=false;
		}
		
		private function stopLessonTimer():void
		{
			this.lessonTimer.stop();
			this.isLessonTimerRunning_bool=false;
			this.lessonCurrentTime_int = 0;
		}
		
		private function syncCurrentTimeWithSeekBar(infoObj_object:Object):void
		{
			this.lessonCurrentTime_int = infoObj_object.time;
			this.sendInfoToLessonComponents(infoObj_object);
		}
		
		private function syncLessonTimeWithComponent(infoObj_object:Object):void
		{
			this.lessonCurrentTime_int = infoObj_object.time;
			var infoObj_object:Object = new Object;
			infoObj_object.message = "updateCurrentTime";
			infoObj_object.time = this.lessonCurrentTime_int;
			this.sendInfoToStage(infoObj_object);
		}
		
		private function syncComponentsToLessonTime():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message="updateCurrentTime";
			infoObj_object.time = this.lessonCurrentTime_int;
			this.sendInfoToLessonComponents(infoObj_object);
		}
		//---------------------------------------------------------------------------------------------------------------------------------//
		
		//------------------------------------Communication functions----------------------------------------------------------------------//
		public function incomingMessageGateway(infoObj_object:Object):void
		{
			var message_string:String = infoObj_object.message.toString();
			trace("TabbedLessonModel ---> incomingMessgeGateway --> Message : "+ message_string);
			
			switch(message_string)
			{
				case "windowClosed":
					this.stopLessonTimer();
					this.unregisterModelFromNativeContainer();
					//this.closeWindow();
					var infoObj_object:Object = new Object;			
					infoObj_object.message = "close";
					this.sendInfoToLessonComponents(infoObj_object);
					break;
				
				case "closeTabbedLesson":
					var infoObj2_object:Object = new Object;
					infoObj2_object.message = "tabRemovalConfirmed";
					this.sendInfoToStage(infoObj2_object);
					this.pauseLessonTimer();
					var infoObj_object:Object = new Object;			
					infoObj_object.message = "close";
					this.sendInfoToLessonComponents(infoObj_object);
					break;
								
				case "openNewComponent":
					this.instantiateComponent(infoObj_object);
					trace("TabbedLessonModel---> component model registered---->lessonComponentsModel_array.length :"+this.lessonComponentsModel_array.length+" this.lessonComponentsName_array.length : "+this.lessonComponentsName_array.length);
					break;
				
				case "unregisterComponentModel":
					this.unregisterComponentModel(infoObj_object);
					trace("TabbedLessonModel---> component model unregistered---->lessonComponentsModel_array.length :"+this.lessonComponentsModel_array.length+" this.lessonComponentsName_array.length : "+this.lessonComponentsName_array.length);
					break;
				
				case "saveLesson":
					this.saveLesson();
					break;
					
				case "lessonPlayedFromControlPanel":
					this.lessonPlayedFromControlPanel();
					break;
					
				case "lessonPausedFromControlPanel":
					this.lessonPausedFromControlPanel();
					break;
				
				case "lessonStoppedFromControlPanel":
					this.lessonStoppedFromControlPanel();
					break;
					
				case "disableLesson":
					this.pauseLessonTimer();
					break;
					
				case "enableLesson":
					this.enableLesson();
					break;
					
				case "syncCurrentTimeWithSeekBar":
					this.syncCurrentTimeWithSeekBar(infoObj_object);
					break;
					
				case "changeInitiated":
					this.lessonChangeInitiated();
					break;
					
				case "changeComplete":
					this.lessonChangeFinished();
					break;
					
					
				case "syncLessonTimeWithComponent":
					this.syncLessonTimeWithComponent(infoObj_object);
					break;
					
				case "lessonPlayedFromStreamingComponents":
					this.lessonPlayedFromStreamingComponents();
					break;
					
				case "lessonPausedFromStreamingComponents":
					this.lessonPausedFromStreamingComponents();
					break;
					
				case "lessonStoppedFromStreamingComponents":
					this.lessonStoppedFromStreamingComponents(infoObj_object);
					break;
					
				case "setEditModeStatus":
					this.lessonEditMode_bool = infoObj_object.editMode;
					this.sendInfoToLessonComponents(infoObj_object);
					break;
					
				case "mouseUpEvent":
					trace("TabbedLessonModel------->event:mouseup  infoObj.event :"+infoObj_object.event);
					this.sendInfoToLessonComponents(infoObj_object);
					break;
			}
		}
		
		private function enableLesson():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "tabbedLessonEnabled";
			infoObj_object.time = this.lessonCurrentTime_int;
			this.sendInfoToStage(infoObj_object);
		}
		
		private function sendInfoToStage(infoObj_object:Object):void
		{
			this.stage_lessonContainer.incomingMessageGateway(infoObj_object);
		}
		
		private function sendInfoToLessonComponents(infoObj_object:Object):void
		{
			for each(var model:Object in this.lessonComponentsModel_array)
			{
				model.incomingMessageGateway(infoObj_object);
			}
		}
		//---------------------------------------------------------------------------------------------------------------------------------//
		
	}
}